package com.abc.tacos.controller;

import com.abc.tacos.bean.Order;
import com.abc.tacos.bean.User;
import com.abc.tacos.config.OrderProps;
import com.abc.tacos.dao.OrderRepository;
import com.abc.tacos.dao.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

import javax.validation.Valid;
import java.security.Principal;


/**
 * @author Kar
 * @version 1.0
 * @date 2022/4/16 11:51
 */
@Slf4j
@Controller
@RequestMapping("/orders")
@SessionAttributes("order")
// @ConfigurationProperties(prefix = "taco.orders")
public class OrderController {

    private final OrderRepository orderRepository;
    private final UserRepository userRepository;
    // private int pageSize = 20;
    private OrderProps orderProps;

    // public void setPageSize(int pageSize) {
    //     this.pageSize = pageSize;
    // }


    public OrderController(OrderRepository orderRepository, UserRepository userRepository, OrderProps orderProps) {
        this.orderRepository = orderRepository;
        this.userRepository = userRepository;
        this.orderProps = orderProps;
    }

    @GetMapping
    public String orderForUser(@AuthenticationPrincipal User user, Model model){
        // Pageable pageable = PageRequest.of(0, pageSize);
        Pageable pageable = PageRequest.of(0, orderProps.getPageSize());
        model.addAttribute("orders",
                orderRepository.findByUserOrderByPlacedAtDesc(user, pageable));
        return "orderList";
    }



    @GetMapping("/current")
    public String orderForm(/*Model model*/) {
        // 已经使用sessionAttribute注入了order数据
        // model.addAttribute("order", new Order());
        return "orderForm";
    }

    /**
     * 四种设置用户user的方式：
     * 1. 获取安全上下文（SecurityContext）中的一个Authentication对象，
     * 从而获取其中的Principal对象，这里的Principal对象就是一个User对象。
     *
     * 2. 注入Principal对象，根据Principal对象中存储的认证用户名，
     * 查询数据库获取User对象。
     *
     * 3. 从注入的Authentication对象中获取User对象
     *
     * 4. 使用@AuthenticationPrincipal注解，注入认证过的User对象。（最简单）
     *
     * @param order
     * @param errors
     * @param sessionStatus
     * @param user
     * @return
     */
    @PostMapping
    public String processOrder(
            @Valid Order order,
            Errors errors,
            SessionStatus sessionStatus,
            // 方式2：
            //Principal principal
            // 方式3：
            //Authentication authentication
            // 方式4：
            @AuthenticationPrincipal User user
    ) {
        if (errors.hasErrors()) {
            return "orderForm";
        }
        //log.info("order:"+order.hashCode());
        // 方式1： 从SecurityContext中获取
        //User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        // 方式2：根据Principal获取
        //User user = userRepository.findByUsername(principal.getName());
        
        // 方式3：从Authentication对象中获取
        //User user = (User) authentication.getPrincipal();
        order.setUser(user);
        orderRepository.save(order);
        // 重置SessionAttributes
        sessionStatus.setComplete();
        log.info("Order submitted: " + order);
        return "redirect:/orders";
    }
}
